package com.nsw99.session;

import java.util.Date;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;

import javax.servlet.ServletContext;
import javax.servlet.http.HttpSession;
import javax.servlet.http.HttpSessionContext;

import com.nsw99.cache.CacheManager;
import com.nsw99.cache.ICache;

/**
 *
 * @author helin
 * @email hl_0074@sina.com
 * @date 2016年8月9日
 */
@SuppressWarnings("deprecation")
public class RedisSession implements HttpSession {

	public static String CLUSTER_KEY = "SVR_CLS_SID";

	private HttpSession session; // container session
	private String sid;
	private boolean change = false;
	private ICache cache;

	private boolean valide = true;

	@SuppressWarnings("unchecked")
	public RedisSession(String sid, HttpSession session) {

		this.session = session;
		this.sid = sid;

		if (!valide) { return; }

		cache = CacheManager.getCache("session");
		if (!RedisSessionClusterFilter.SESSION_STICKY || this.session.isNew()) {
			// load from cache
			Map<String, ?> map = (Map<String, ?>) cache.get(this.sid);
			if (map != null) {
				for (Entry<String, ?> entry : map.entrySet()) {
					this.session.setAttribute(entry.getKey(), entry.getValue());
				}
			}
		}
	}

	@Override
	public Object getAttribute(String key) {

		return this.session.getAttribute(key);
	}

	@Override
	public Enumeration<String> getAttributeNames() {

		return this.session.getAttributeNames();
	}

	@Override
	public long getCreationTime() {

		return this.session.getCreationTime();
	}

	@Override
	public String getId() {

		return this.session.getId();
	}

	@Override
	public long getLastAccessedTime() {

		return this.session.getLastAccessedTime();
	}

	@Override
	public int getMaxInactiveInterval() {

		return this.session.getMaxInactiveInterval();
	}

	@Override
	public ServletContext getServletContext() {

		return this.session.getServletContext();
	}

	@Override
	@Deprecated
	public HttpSessionContext getSessionContext() {

		return this.session.getSessionContext();
	}

	@Override
	@Deprecated
	public Object getValue(String key) {

		return this.session.getValue(key);
	}

	@Override
	@Deprecated
	public String[] getValueNames() {

		return this.session.getValueNames();
	}

	@Override
	public boolean isNew() {

		return this.session.isNew();
	}

	@Override
	@Deprecated
	public void putValue(String key, Object value) {

		change = true;
		this.session.putValue(key, value);
	}

	@Override
	public void removeAttribute(String key) {

		change = true;
		this.session.removeAttribute(key);
	}

	@Override
	@Deprecated
	public void removeValue(String key) {

		change = true;
		this.session.removeValue(key);
	}

	@Override
	public void setAttribute(String key, Object value) {

		change = true;
		this.session.setAttribute(key, value);
	}

	@Override
	public void setMaxInactiveInterval(int interval) {

		this.session.setMaxInactiveInterval(interval);
	}

	/**
	 * 会话同步
	 */
	public void sync() {

		if (!valide) { return; } // 已执行了过期操作

		if (!change) {
			// refresh cache expire time
			if (((new Date().getTime() - this.session.getLastAccessedTime()) / 1000) < 60) {
				cache.expire(this.sid, this.session.getMaxInactiveInterval());
			}
			return;
		}
		Map<String, Object> attrs = new HashMap<>();

		Enumeration<String> enums = this.session.getAttributeNames();
		while (enums.hasMoreElements()) {
			String key = enums.nextElement();
			attrs.put(key, this.session.getAttribute(key));
		}
		cache.put(this.sid, attrs, this.getMaxInactiveInterval());
	}

	@Override
	public void invalidate() {

		valide = false;
		this.session.invalidate();
		this.cache.remove(this.sid);
	}

	/**
	 * @return
	 */
	public boolean isValide() {

		return valide;
	}
}
